package at.ac.univie.ise.generator;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jooq.impl.Factory;

import at.ac.univie.ise.common.Config;
import at.ac.univie.ise.schema.Tables;
import at.ac.univie.ise.schema.tables.records.CityRecord;
import at.ac.univie.ise.schema.tables.records.CustomerRecord;
import at.ac.univie.ise.schema.tables.records.LicenceRecord;
import at.ac.univie.ise.schema.tables.records.PersonRecord;
import at.ac.univie.ise.schema.tables.records.WebuserRecord;
import de.pyranja.util.DateUtils;
import de.pyranja.util.Utils;

public class PersonGenerator {

	// logger
	private final Log log = LogFactory.getLog(PersonGenerator.class);
	
	private final Factory create;
	private final EntityComponents ec;
	private final Random rng;
	
	private List<CityRecord> cities;
	private List<PersonContainer> persons;
	
	public PersonGenerator(Factory f) {
		log.info(">> generating persons");
		ec = EntityComponents.getInstance();
		create = f;
		rng = Config.getInstance().getRng();
		cities = create.fetch(Tables.CITY);
		persons = new LinkedList<>();
		generate();
		log.info("<< "+ persons.size() +" persons generated");
	}
	
	private void generate() {
		PersonContainer temp = null;
		for (int i = 0; i < Config.getInstance().getPersonScale(); i++) {
			temp = new PersonContainer();
			temp.setPerson(generatePerson());
			temp.setCustomer(generateCustomer(temp.getPerson()));
			temp.setWebuser(generateWebUser(temp.getPerson()));
			addLicences(temp);
			persons.add(temp);
		}
	}
	
	private PersonRecord generatePerson() {
		boolean male = ec.randomSex();
		PersonRecord res = create.newRecord(Tables.PERSON);
		res.setSalutation(ec.salut(male));
		res.setFirstname(ec.randomFirstName(male));
		res.setLastname(ec.randomLastName());
		res.setEmail(ec.concatEmail(res.getLastname()));
		res.setBorn(DateUtils.toSQLDate(DateUtils.randomAgoDateByYear(rng, 20, 70)));
		res.setPostcode(Utils.randomElem(cities, rng).getPostcode());
		res.setStreet(ec.randomStreet());
		res.setLicencenr(ec.licenceNumber());
		res.setLicencesince(DateUtils.toSQLDate(DateUtils.randomAgoDateByYear(rng, 1, 19)));
		res.store();
		res.refresh();
		if ( log.isTraceEnabled() ) { log.trace("-- generated :"+ res.toString()); }
		return res;
	}
	
	private CustomerRecord generateCustomer(PersonRecord p) {
		CustomerRecord res = create.newRecord(Tables.CUSTOMER);
		res.setPersonid(p.getPersonid());
		if (rng.nextBoolean()) {
			res.setCcnr(Utils.randomNumber(rng, 16));
		} else {
			res.setBic(Utils.randomNumber(rng,11));
			res.setIban(Utils.randomNumber(rng,34));
		}
		byte premium = 0;
		if (rng.nextBoolean()) {
			premium++;
		}
		res.setPremium(premium);
		res.store();
		if ( log.isTraceEnabled() ) { log.trace("-- generated :"+ res.toString()); }
		return res;
	}
	
	private WebuserRecord generateWebUser(PersonRecord p) {
		WebuserRecord res = create.newRecord(Tables.WEBUSER);
		res.setPersonid(p.getPersonid());
		res.setUsername(Integer.toString(p.getPersonid()));
		res.setPwhash("test");
		res.setSalt("test");
		res.store();
		if ( log.isTraceEnabled() ) { log.trace("-- generated :"+ res.toString()); }
		return res;
	}
	
	private void addLicences(PersonContainer p) {
		LicenceRecord temp = null;
		for (String licClass : ec.getLicences()) {
			temp = create.newRecord(Tables.LICENCE);
			temp.setPersonid(p.getPerson().getPersonid());
			temp.setClassname(licClass);
			temp.store();
			if ( log.isTraceEnabled() ) { log.trace("-- generated :"+ temp.toString()); }
			p.getLicences().add(temp);
			if (rng.nextBoolean()) {
				break;
			}
		}
	}

	/**
	 * @return the persons
	 */
	public List<PersonContainer> getPersons() {
		return persons;
	}
}
